package com.obradovicnjegovan.webprodavnica.controller;

import java.text.DecimalFormat;
import java.util.List;

import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.*;
import org.tynamo.security.services.SecurityService;

import com.obradovicnjegovan.webprodavnica.entities.Kategorija;
import com.obradovicnjegovan.webprodavnica.entities.Korisnik;
import com.obradovicnjegovan.webprodavnica.entities.Korpa;
import com.obradovicnjegovan.webprodavnica.entities.Narudzbenica;
import com.obradovicnjegovan.webprodavnica.entities.OdabranProizvod;
import com.obradovicnjegovan.webprodavnica.entities.Proizvod;
import com.obradovicnjegovan.webprodavnica.entities.StatusNarudzbenice;
import com.obradovicnjegovan.webprodavnica.so.KreirajNovuNarudzbenicu;
import com.obradovicnjegovan.webprodavnica.so.Obrisi;
import com.obradovicnjegovan.webprodavnica.so.PonistiNarudzbenicu;
import com.obradovicnjegovan.webprodavnica.so.Pronadji;
import com.obradovicnjegovan.webprodavnica.so.PronadjiNajnovijeProizvode;
import com.obradovicnjegovan.webprodavnica.so.PronadjiSve;
import com.obradovicnjegovan.webprodavnica.so.SacuvajIliAzuriraj;
import com.obradovicnjegovan.webprodavnica.so.UbaciProizvodUKorpu;

public class ControllerAlImpl implements ControllerAL{
	@Inject
	private SacuvajIliAzuriraj<Kategorija> siaKategorija;
	@Inject
	private SacuvajIliAzuriraj<Proizvod> siaProizvod;
	@Inject
	private SacuvajIliAzuriraj<Korpa> siaKorpa;
	@Inject
	private SacuvajIliAzuriraj<OdabranProizvod> siaOdabranProizvod;
	@Inject
	private SacuvajIliAzuriraj<Narudzbenica> siaNarudzbenica;
	
	@Inject
	private Pronadji<Proizvod> pronadjiProizvod;
	@Inject
	private Pronadji<Korpa> pronadjiKorpu;
	@Inject
	private Pronadji<Narudzbenica> pronadjiNarudzbenicu;
	
	@Inject
	private PronadjiSve<Narudzbenica> sveNarudzbenice;
	@Inject
	private PronadjiSve<Kategorija> sveKategorije;
	@Inject
	private PronadjiSve<Proizvod> sviProizvodi;
	@Inject
	private PronadjiSve<Korisnik> sviKorisnici;
	@Inject
	private PronadjiSve<OdabranProizvod> sviOdabraniProizvodi;
	
	@Inject
	private Obrisi<Proizvod> obrisiProizvod;
	@Inject
	private Obrisi<Kategorija> obrisiKategoriju;
	@Inject 
	private Obrisi<OdabranProizvod> obrisiOdabranProizvod;

	@Inject
	private UbaciProizvodUKorpu ubaciProizvodUKorpu;
	@Inject
	private KreirajNovuNarudzbenicu kreirajNovuNarudzbenicu;
	@Inject
	private PonistiNarudzbenicu ponistiNarudzbenicu;
	@Inject
	private PronadjiNajnovijeProizvode pronadjiNajnovijeProizvode;


	
	public static final String AUTH_TOKEN = "authToken";
    private static Request request;
    private String message;
	
	
	public Request getRequest() {
		return request;
	}

	public void setRequest(Request request) {
		ControllerAlImpl.request = request;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
	
	
	public boolean preuzmiKorpu(Korpa korpa) {
		try {
			request.getSession(true).setAttribute(AUTH_TOKEN, korpa);
			return true;
		} catch (Exception e) {
			// TODO: handle exception
		}
		return false;
	}
	public boolean ostaviKorpu(){
		try {
			Session session = request.getSession(false);
			if (session != null) {
                session.setAttribute(AUTH_TOKEN, null);
                session.invalidate();
                return true;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return false;
	}
	public boolean daLiKorpaPostoji(){
		try {
			Session session = request.getSession(false);
			if (session != null) {
                return session.getAttribute(AUTH_TOKEN) != null;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return false;
	}
	public Korpa getKorpa(){
		try {
			if (daLiKorpaPostoji()) {
				return (Korpa) request.getSession(true).getAttribute(AUTH_TOKEN);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
	
	
	

	public String sacuvajKategoriju(Kategorija k) {
		siaKategorija.setObject(k);
		return (String) siaKategorija.execute();
	}
	public String sacuvajProizvod(Proizvod p) {
		siaProizvod.setObject(p);
		return (String) siaProizvod.execute();
	}
	public String sacuvajNarudzbenicu(Narudzbenica n) {
		siaNarudzbenica.setObject(n);
		return (String) siaNarudzbenica.execute();
	}
	public void sacuvajKorpu(Korpa korpa) {
		siaKorpa.setObject(korpa);
		siaKorpa.execute();
	}
	public void sacuvajOdabranProizvod(OdabranProizvod od) {
		siaOdabranProizvod.setObject(od);
		siaOdabranProizvod.execute();
	}
	
	

	public Proizvod pronadjiProizvod(long id) {
		pronadjiProizvod.setId(id);
		pronadjiProizvod.setKlasa(Proizvod.class);
		return (Proizvod) pronadjiProizvod.execute();
	}
	public Narudzbenica pronadjiNarudzbenicu(long id) {
		pronadjiNarudzbenicu.setId(id);
		pronadjiNarudzbenicu.setKlasa(Narudzbenica.class);
		return (Narudzbenica) pronadjiNarudzbenicu.execute();
	}
	public Korpa pronadjiKorpu(long id) {
		pronadjiKorpu.setId(id);
		pronadjiKorpu.setKlasa(Korpa.class);
		return (Korpa) pronadjiKorpu.execute();
	}
	public Korisnik pronadjiKoriznika(Object principal) {
		for (Korisnik k : pronadjiSveKlijente()) {
			if (principal.equals(k.getUsername())) {
				return k;
			}
		}
		return null;
	}



	@SuppressWarnings("unchecked")
	public List<Narudzbenica> pronadjiSveNarudzbenice() {
		sveNarudzbenice.setKlasa(Narudzbenica.class);
		return (List<Narudzbenica>) sveNarudzbenice.execute();
	}
	@SuppressWarnings("unchecked")
	public List<Kategorija> pronadjiSveKategorije() {
		sveKategorije.setKlasa(Kategorija.class);
		return (List<Kategorija>) sveKategorije.execute();
	}
	@SuppressWarnings("unchecked")
	public List<Proizvod> pronadjiSveProizvode() {
		sviProizvodi.setKlasa(Proizvod.class);
		return (List<Proizvod>) sviProizvodi.execute();
	}
	@SuppressWarnings("unchecked")
	public List<Korisnik> pronadjiSveKlijente() {
		sviKorisnici.setKlasa(Korisnik.class);
		return (List<Korisnik>) sviKorisnici.execute();
	}
	@SuppressWarnings("unchecked")
	public List<OdabranProizvod> pronadjiSveOdabraneProizvode() {
		sviOdabraniProizvodi.setKlasa(OdabranProizvod.class);
		return (List<OdabranProizvod>) sviOdabraniProizvodi.execute();
	}

	public OdabranProizvod ubaciProizvodUKorpu(Proizvod p, Korpa k, int kolicina) {
		ubaciProizvodUKorpu.odaberiProizvod(p, k, kolicina);
		return (OdabranProizvod) ubaciProizvodUKorpu.execute();
	}
	
	
	
	public String obrisiProizvod(Proizvod p) {
		if (p.getOdabraniProizvodi().isEmpty()) {
			obrisiProizvod.setObjekat(p);
			return (String) obrisiProizvod.execute();
		} else {
			return "Proizvod se vec nalazi u nekoj narudzbini";
		}
	}
	public String obrisiKategoriju(Kategorija kat) {
		if (kat.getProizvodi().isEmpty()) {
			obrisiKategoriju.setObjekat(kat);
			return (String) obrisiKategoriju.execute();
		} else {
			return "Kategorija \""+kat.getNazivKategorije()+"\" sadrzi proizvode.";
		}
		
	}
	public void obrisiOdabranProizvod(OdabranProizvod odabranProizvod) {
		obrisiOdabranProizvod.setObjekat(odabranProizvod);
		obrisiOdabranProizvod.execute();
	}



	
	
	
	public Narudzbenica kreirajNovuNarudzbenicu(Korpa k) {
		kreirajNovuNarudzbenicu.setKorpa(k);
		return (Narudzbenica) kreirajNovuNarudzbenicu.execute();
	}

	public String ponistiNarudzbenicu(Narudzbenica n) {
		ponistiNarudzbenicu.setNarudzbenica(n);
		return (String) ponistiNarudzbenicu.execute();
	}
	
	public List<Proizvod> najnovijiProizvodi(int n){
		pronadjiNajnovijeProizvode.setBrojProivoda(n);
		return (List<Proizvod>) pronadjiNajnovijeProizvode.execute();
	}



	public String formatDouble(double d){
		DecimalFormat df = new DecimalFormat("0.00");
		return df.format(d);
	}
	public String getUkupanPrihod() {
		double ukupanPrihod = 0l;
		try {
			for (Narudzbenica n : pronadjiSveNarudzbenice()) {
				if (!n.getStatusNarudzbenice().equals(StatusNarudzbenice.ponistena)) {
					ukupanPrihod = ukupanPrihod + n.getKorpa().getUkupnaCena();
				}
			}
		} catch (Exception e) {
		}
		return formatDouble(ukupanPrihod);
	}
	public String getSumaPlacenihNarudzbina() {
		double ukupanUplaceno = 0l;
		try {
			for (Narudzbenica n : pronadjiSveNarudzbenice()) {
				if (n.getStatusNarudzbenice() != StatusNarudzbenice.ponistena) {
					if (n.getStatusNarudzbenice() == StatusNarudzbenice.placena ) {
						ukupanUplaceno = ukupanUplaceno + n.getKorpa().getUkupnaCena();
					}
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return formatDouble(ukupanUplaceno);
	}
	public String getSumaNarudzbinaNaCekanju() {
		double ukupanUplaceno = 0l;
		try {
			for (Narudzbenica n : pronadjiSveNarudzbenice()) {
				if (n.getStatusNarudzbenice() != StatusNarudzbenice.ponistena) {
					if (n.getStatusNarudzbenice() == StatusNarudzbenice.naCekanju ) {
						ukupanUplaceno = ukupanUplaceno + n.getKorpa().getUkupnaCena();
					}
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return formatDouble(ukupanUplaceno);
	}

	@Inject
	private SacuvajIliAzuriraj<Korisnik> siaKorisnik;
	
	@Override
	public void registrujKorisnika(Korisnik korisnik) {
		try {
			siaKorisnik.setObject(korisnik);
			siaKorisnik.execute();

		} catch (Exception e) {
			// TODO: handle exception
		}
	}

}
